/**
 * @Author: joker
 * @Date: 2024-12-27 15:45:35
 * @LastEditors: joker
 * @LastEditTime: 2024-12-27 17:12:57
 * @FilePath: \aegis-admin-front\test\excel\util.js
 * @Description:
 */
import ExcelJS from "exceljs";
import { getToken } from "@/utils/auth";
import { tansParams } from "@/utils/ruoyi";

/**
 * Excel导出函数
 * @param {Object} options - 导出配置项
 * @param {Array} options.data - 导出数据
 * @param {Array} options.headers - 表头配置
 * @param {string} options.filename - 文件名
 * @param {Array} options.imageColumns - 图片列
 */
export const exportExcel = async ({
  data = [],
  headers = [],
  filename = "导出文件",
  imageColumns = [],
  options = {
    width: 20,
    height: 30,
  },
}) => {
  try {
    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet("Sheet1", {
      properties: { defaultRowHeight: 60 },
    });

    // 设置列宽
    worksheet.columns = headers.map((header) => ({
      width: header.width || options.width,
    }));

    // 手动设置表头
    const headerRow = worksheet.getRow(1);
    headers.forEach((header, index) => {
      const cell = headerRow.getCell(index + 1);
      cell.value = header.label;
      cell.font = { bold: true };
      cell.alignment = { vertical: "middle", horizontal: "center" };
    });
    headerRow.height = 30;
    headerRow.commit();

    // 添加数据
    for (let i = 0; i < data.length; i++) {
      const row = data[i];
      const rowData = { ...row };
      imageColumns.forEach((col) => {
        rowData[col] = "";
      });

      const rowNumber = i + 2;
      const newRow = worksheet.getRow(rowNumber);

      // 设置每个单元格的值
      headers.forEach((header, index) => {
        newRow.getCell(index + 1).value = rowData[header.key];
      });
      newRow.height = options.height;

      // 处理图片
      for (const col of imageColumns) {
        if (row[col]) {
          const response = await fetch(row[col]);
          const buffer = await response.arrayBuffer();
          const imageId = workbook.addImage({
            buffer,
            extension: "jpeg",
          });

          const colNumber = headers.findIndex((h) => h.key === col) + 1;
          worksheet.addImage(imageId, {
            tl: { col: colNumber - 1, row: rowNumber - 1 },
            br: { col: colNumber, row: rowNumber },
            editAs: "oneCell",
          });
        }
      }

      // 设置数据行的样式
      newRow.eachCell((cell) => {
        cell.alignment = {
          vertical: "middle",
          horizontal: "center",
        };
      });

      newRow.commit();
    }

    // 导出文件
    await workbook.xlsx.writeBuffer().then((buffer) => {
      const blob = new Blob([buffer], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      });
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `${filename}.xlsx`;
      a.click();
      window.URL.revokeObjectURL(url);
    });
  } catch (error) {
    console.error("导出失败:", error);
    throw new Error("导出失败");
  }
};

/**
 * @description: 导出文件
 * @param {*} url
 * @param {*} params
 * @return {*}
 */
export const exportExcelFromAPI = (url, params) => {
  const downloadUrl = `${process.env.VUE_APP_BASE_API}${url}?${tansParams(params).replace(/&$/, '')}`;

  // 创建一个隐藏的a标签用于下载
  const link = document.createElement('a');
  link.style.display = 'none';
  link.href = downloadUrl;

  // 发起请求获取文件
  fetch(downloadUrl, {
    method: 'GET',
    headers: {
      Authorization: "Bearer " + getToken(),
    },
  })
    .then(async response => {
      // 保存content-disposition用于后续获取文件名
      const contentDisposition = response.headers.get('content-disposition');
      
      // 读取response body stream
      const reader = response.body.getReader();
      const chunks = [];
      
      while(true) {
        const {done, value} = await reader.read();
        if(done) break;
        chunks.push(value);
      }

      // 合并chunks为一个Uint8Array
      const allChunks = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0));
      let position = 0;
      for(const chunk of chunks) {
        allChunks.set(chunk, position);
        position += chunk.length;
      }

      // 创建blob
      const blob = new Blob([allChunks], {
        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      });

      // 创建blob链接
      const url = window.URL.createObjectURL(blob);
      link.href = url;

      // 从响应头中获取文件名,如果没有则使用默认名称
      const fileName = contentDisposition ?
        decodeURI(contentDisposition.split('filename=')[1]) :
        'export.xlsx';

      link.setAttribute('download', fileName);
      document.body.appendChild(link);
      link.click();

      // 清理
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);
    })
    .catch(err => {
      console.error('下载文件失败:', err);
      throw new Error('下载文件失败');
    });
};

/**
 * @description: 拼接的URL请求参数
 * @param {*} params
 * @return {*}
 */
const queryStringParams = params => {
  return Object.keys(params)
    .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
    .join('&');
};